classdef v1_neuron
    properties
        bgRate
        maxRate
        sfTuning
        tfTuning
        ctrTuning
        orTuning
        rfCen
        rfSize
        firingStats = 'poissrnd';
    end
    methods
        function s = v1_neuron(bgRate,maxRate,sfTuningObj,tfTuningObj,ctrTuningObj,orTuningObj,rfCen,rfSize,firingStats)
            switch nargin
                case 0 % no inputs...create empty object
                    s.bgRate = NaN;
                    s.maxRate = NaN;
                    s.sfTuning = [];
                    s.tfTuning = [];
                    s.ctrTuning = [];
                    s.orTuning = [];
                    s.rfCen = [];
                    s.rfSize = [];
                case 9 % every single data is provided
                    if isnumeric(bgRate)
                        s.bgRate = bgRate;
                    else
                        error('v1_neuron:wrongType','bgRate has to be a numeric type');
                    end
                    
                    if isnumeric(maxRate)
                        s.maxRate = maxRate;
                    else
                        error('v1_neuron:wrongType','maxRate has to be a numeric type');
                    end
                    
                    if isa(sfTuningObj,'sfTuning')
                        s.sfTuning = sfTuningObj;
                    else
                        error('v1_neuron:wrongType','sfTuningObj has to be a sfTuning object');
                    end
                    
                    if isa(tfTuningObj,'tfTuning')
                        s.tfTuning = tfTuningObj;
                    else
                        error('v1_neuron:wrongType','tfTuningObj has to be a tfTuning object');
                    end
                    
                    if isa(ctrTuningObj,'ctrTuning')
                        s.ctrTuning = ctrTuningObj;
                    else
                        error('v1_neuron:wrongType','ctrTuningObj has to be a ctrTuning object');
                    end
                    
                    if isa(orTuningObj,'orTuning')
                        s.orTuning = orTuningObj;
                    else
                        error('v1_neuron:wrongType','orTuningObj has to be a orTuning object');
                    end
                    
                    if isnumeric(rfCen)
                        s.rfCen = rfCen;
                    else
                        error('v1_neuron:wrongType','rfCen has to be numeric');
                    end
                    
                    if isnumeric(rfSize)
                        s.rfSize = rfSize;
                    else
                        error('v1_neuron:wrongType','rfSize has to be numeric');
                    end
                    
                    if ischar(firingStats)&& ismember(firingStats,{'poissrnd'})
                        s.firingStats = firingStats;
                    else
                        error('v1_neuron:firingStats','firingStats has to be one of ''poissrnd'',');
                    end
            end
        end
        
        function out = sample(s,stimulus)
            if ~isa(stimulus,'stim')
                error('v1_neuron:wrongInputType','stimulus needs to be a stim');
            end
            sfSample = sample(s.sfTuning,stimulus);
            tfSample = sample(s.tfTuning,stimulus);
            orSample = sample(s.orTuning,stimulus);
            ctrSample = sample(s.ctrTuning,stimulus);
            fRate = s.bgRate+(s.maxRate-s.bgRate)*sfSample*tfSample*orSample*ctrSample;
            switch s.firingStats
                case 'poissrnd'
                    out = poissrnd(fRate);
                otherwise
                    error('v1_neuron:unknownSamplingMethod','firingStats has to be one of ''poissrnd'',');
            end
        end
    end
end